//
//  DYArrayDataSource.m
//  ISmartHome
//
//  Created by JM on 15/7/29.
//
//

#import "DYArrayDataSource.h"
#import <YYCategories.h>
#import <MJExtension.h>
#import <XPGWifiSDK/XPGWifiSDK.h>
#import "Device.h"
#import "AppDelegate.h"
@interface DYArrayDataSource ()

@property (nonatomic, copy)   NSString *cellIdentifier;
@property (nonatomic, copy)   NSString *cellXibName;
@property (nonatomic, copy)   CellConfigureBlock configureCellBlock;

@end

@implementation DYArrayDataSource

singleton_implementation(DYArrayDataSource)
- (NSMutableArray *)removedItems{
    if (!_removedItems) {
        _removedItems = [NSMutableArray array];
    }
    return _removedItems;
}

#pragma mark-
//todo 改为成员函数
- (NSString *)documentfilePath {
    if (!self.userID){
        return nil;
    }
    
    NSString *strFileNamePath = [NSString stringWithFormat:@"%@.plist",self.userID];
    
    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory
                                                       , NSUserDomainMask
                                                       , YES);
    NSString *stringPath = [paths objectAtIndex:0];
    stringPath = [stringPath stringByAppendingPathComponent:strFileNamePath];
    return  stringPath;
}
- (BOOL)saveItems{
    // Encoding
    return [NSKeyedArchiver archiveRootObject:self.items toFile:[self documentfilePath]];
}

+ (id)dataSourceFromSaveFileWithCellId:(NSString *) aID ConfigCellBlock:(CellConfigureBlock) aBLock{
    // Decoding
    DYArrayDataSource *source = [DYArrayDataSource sharedDYArrayDataSource];
    
    NSArray *items = [NSKeyedUnarchiver unarchiveObjectWithFile:[source documentfilePath]];
    for (Device *devie in items){
        devie.xpgDevice.delegate = [DYArrayDataSource sharedDYArrayDataSource];
    }
    [source setItems:items cellIdentifier:aID configCellBlock:aBLock];
    [source setArray:items];
    
    source.cellXibName = @"DeviceCell";
    return source;
    
}


+ (id)dataSourceWithItems:(NSArray *)aItems
           cellIdentifier:(NSString *) aID
          configCellBlock:(CellConfigureBlock) aBLock{
    DYArrayDataSource *source = [DYArrayDataSource sharedDYArrayDataSource];
    [source setItems:aItems cellIdentifier:aID configCellBlock:aBLock];
    source.cellXibName = @"DeviceCell";
    return source;
}

- (void)setItems:(NSArray *)aItems cellIdentifier:(NSString *) aID configCellBlock:(CellConfigureBlock) aBLock {
    for (Device *devie in aItems){
        devie.xpgDevice.delegate = [DYArrayDataSource sharedDYArrayDataSource];
    }
    self.items = [aItems mutableCopy];
    self.cellIdentifier = aID;
    self.configureCellBlock = aBLock;
}

//- (id) initWithItems:(NSArray *)aItems cellIdentifier:(NSString *) aID configCellBlock:(CellConfigureBlock) aBLock{
//    if (self = [super init]){
//        self.items = [aItems mutableCopy];
//        self.cellIdentifier = aID;
//        self.configureCellBlock = aBLock;
//    }
//    return self;
//}

- (void)setArray:(NSArray *)items{
    self.items = [items mutableCopy];
}

- (id)itemAtIndex:(NSUInteger )index {
    if (index < self.items.count){
        return self.items[index];
    }
    return nil;
}

- (NSInteger)count {
    return self.items.count;
}

- (void)addItem:(id) aItem {
    if (!_items) {
        _items = [NSMutableArray array];
    }
     [self.items addObject:aItem];
}
- (void)removeItem:(id) aItem ;{
    [self.items removeObject:aItem];
}
- (void)replaceItemAtIndex:(NSInteger)aIndex withItem:(id)aItem {
    [_items replaceObjectAtIndex:aIndex withObject:aItem];
}

- (BOOL)itemSearchWithEqualBlock:(ItemEuqalBlock)aEqualBlock; {
    for (NSInteger i=0; i<_items.count; i++) {
        id item = _items[i];
        if(aEqualBlock(item)) {
//            [_items replaceObjectAtIndex:i withObject:aItem];
            return YES;
        }
    }
    return NO;
}

- (instancetype)itemWithMacAdress:(NSString *)adress {
    for (NSInteger i=0; i<_items.count; i++) {
        Device *device = _items[i];
        if([device.macAddress isEqualToString:adress]) {
            return _items[i];
        }
    }
    return nil;
}

//- (BOOL)replaceItem:(id)aSourceItem withItem:(id)aItem {
//    BOOL found = NO;
//    for (id item in _items) {
//        if (1) {
//            [_items replaceObjectAtIndex:4 withObject:nil];
//        }
//        
//    }
//    return found;
//}
- (void)addOrReplaceItem:(id) aItem {
    for (id item in _items) {
        [_items replaceObjectAtIndex:4 withObject:nil];
    }
}

- (void)insertObject:(id)aItem atIndex:(NSUInteger)aIndex; {
    if (!_items) {
        _items = [NSMutableArray array];
    }
    [self.items insertObject:aItem atIndex:aIndex];
   
}

- (BOOL)containsObject:(id)aItem; {

    return [self.items containsObject:aItem];
}
@end




@implementation DYArrayDataSource(UITableViewDataSource)

- (id)itemAtIndexPath:(NSIndexPath*)indexPath {
    return self.items[(NSUInteger)indexPath.row];
}


- (NSInteger)tableView:(UITableView*)tableView
 numberOfRowsInSection:(NSInteger)section {
    return self.items.count;
}

- (UITableViewCell*)tableView:(UITableView*)tableView
        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    
    
    //[tableView registerClass:_cellClass forCellReuseIdentifier:_cellIdentifier];
    
//    DeviceCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier];
//        if (!cell) {
//            cell = [DeviceCell cell];
//        }
    [tableView registerNib:[UINib nibWithNibName:self.cellXibName bundle:nil] forCellReuseIdentifier:self.cellIdentifier];
    id cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];
    id item = [self itemAtIndexPath:indexPath];
    self.configureCellBlock(cell,item);
    return cell;
}


#pragma mark-
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return tableView.editing;
}

// Moving/reordering

// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; {
        return YES;
}

// Index

//- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView __TVOS_PROHIBITED {
//    
//}// return list of section titles to display in section index view (e.g. "ABCD...Z#")
//- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index __TVOS_PROHIBITED; {
//    
//    
//}// tell table which section corresponds to section title/index (e.g. "B",1))

// Data manipulation - insert and delete support

// After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
// Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;{
    if (UITableViewCellEditingStyleDelete){
        __weak DYArrayDataSource *weakSelf = (DYArrayDataSource *)self;
        [tableView updateWithBlock:^(UITableView *tableView) {
            [tableView deleteRowAtIndexPath:indexPath withRowAnimation:UITableViewRowAnimationTop];
             id item = [weakSelf itemAtIndexPath:indexPath];
            [weakSelf.items removeObject:item];
            [self.removedItems addObject:item];
            
        }];
    }
    
}

// Data manipulation - reorder / moving support

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath; {
    id object = [self itemAtIndexPath:sourceIndexPath]; // 获取数据
    [self.items removeObject:object];  //在当前位置删除
    [self insertObject:object atIndex:destinationIndexPath.row];//插入的位置
    
}


#pragma mark -作为设备的数据中心

- (id)delegateOfDevice:(XPGWifiDevice *)aDevice{
    Device *device= [self itemWithMacAdress:aDevice.macAddress];
    return device.deleagete;
}

/**
 设备断开连接的回调接口，返回设备断开连接的接口。当设备主动或被动断开以及异常断开时，也会触发此接口的回调
 @param device 返回触发回调的设备实例
 @param result 设备断开成功或失败
 @see 触发函数：[XPGWifiDevice disconnect]
 */
- (void)XPGWifiDeviceDidDisconnected:(XPGWifiDevice *)device result:(int)result {
    Device *dydevice= [self itemWithMacAdress:device.macAddress];
    [dydevice setXpgDevice:device];
    dydevice.haveReceiveDataState = NO;
    //todo 是否把haveReceiveDataState＝NO呢
     NSLog(@"did%@：断开连接%d",device.did,result);
    id delegate = [self delegateOfDevice:device];
    if (delegate && [delegate respondsToSelector:@selector(XPGWifiDeviceDidDisconnected: result:)]){
        [delegate XPGWifiDeviceDidDisconnected:device result:result];
    }
}

/**
 设备登录的回调接口，返回设备登录结果
 @param device 返回触发回调的设备实例
 @param result 设备登录成功或失败
 @see 枚举XPGWifiLoginErrorCode
 @see 触发函数：[XPGWifiDevice login:token:]
 */
- (void)XPGWifiDevice:(XPGWifiDevice *)device didLogin:(int)result {
    Device *dydevice= [self itemWithMacAdress:device.macAddress];
    [dydevice setXpgDevice:device];
    id delegate = [self delegateOfDevice:device];
    if (delegate && [delegate respondsToSelector:@selector(XPGWifiDevice: didLogin:)]){
        [delegate XPGWifiDevice:device didLogin:result];
    }
}

/**
 设备状态变化的回调接口，返回设备上报的数据内容，包括设备控制命令的应答、设备运行状态的上报、设备报警、设备故障信息
 @param device 返回触发回调的设备实例
 @param result 回调成功或失败
 @param data 设备上报的数据内容
 @note 代码示例
 
 {
 "data": "value", //字符串类型，上报的数据内容
 "alerts": "value", //NSArray类型，报警列表
 "faults": "value", //NSArray类型，故障列表
 "binary": "value", //NSData类型，二进制透传数据
 }
 
 @see 触发函数：[XPGWifiDevice write:]
 */
- (void)XPGWifiDevice:(XPGWifiDevice *)device didReceiveData:(NSDictionary *)data result:(int)result {
    
     Device *dydevice= [self itemWithMacAdress:device.macAddress];
      NSDictionary *_data = [data valueForKey:@"data"];
    if (_data) {
        dydevice.haveReceiveDataState = YES;
        [dydevice setDeviceReceiveData:_data];
    }
    
    if (dydevice.deleagete && [dydevice.deleagete respondsToSelector:@selector(XPGWifiDevice: didReceiveData: result:)]){
        [dydevice.deleagete XPGWifiDevice:device didReceiveData:data result:result];
    }
    [self saveItems];
}

/**
 设备在线状态变化的回调接口，当设备在线状态发生变化时会被触发
 @param device 触发回调的设备实例
 @param isOnline YES=在线，NO=不在线
 @note 触发条件：设备在线状态变化
 */
- (void)XPGWifiDevice:(XPGWifiDevice *)device didDeviceIsOnline:(BOOL)isOnline {
    
    NSLog(@"设备上线 %d",isOnline);
    id delegate = [self delegateOfDevice:device];
    if (delegate && [delegate respondsToSelector:@selector(XPGWifiDevice: didDeviceIsOnline:)]){
        [delegate XPGWifiDevice:device didDeviceIsOnline:isOnline];
    }
}

#ifdef __INTERNAL_SUPPORT_SWITCH_SERVICE_AND_LOG_CACHE__
/*
 回调接口，返回设置设备调试模式的结果
 @param result：0 成功，其他失败
 @see 触发函数：[XPGWifiSDK setSwitchService:]
 */
//- (void)XPGWifiDevice:(XPGWifiDevice *)device didSetSwitcher:(int)result;
#endif

/**
 设备日志上报的回调接口，设备推送日志信息时会被触发
 @param device 触发回调的设备实例
 @param logInfo 日志信息
 @note 触发条件：设备登录后主动上报
 */
//- (void)XPGWifiDevice:(XPGWifiDevice *)device didUpdateDeviceLog:(NSDictionary *)logInfo;

/**
 获取设备硬件信息的回调接口，需要在局域网与设备建立连接后获取。返回获取到的硬件信息
 @param device 触发回调的设备实例
 @param hwInfo 硬件信息
 
 @{
 "XPGWifiDeviceHardwareWifiHardVerKey": "value",
 "XPGWifiDeviceHardwareWifiSoftVerKey": "value",
 "XPGWifiDeviceHardwareMCUHardVerKey": "value",
 "XPGWifiDeviceHardwareMCUSoftVerKey": "value",
 "XPGWifiDeviceHardwareFirmwareIdKey": "value",
 "XPGWifiDeviceHardwareFirmwareVerKey": "value",
 "XPGWifiDeviceHardwareProductKey": "value"
 }
 
 @see 触发函数：[XPGWifiDevice getHardwareInfo]??????????????????
 */
//- (void)XPGWifiDevice:(XPGWifiDevice *)device didQueryHardwareInfo:(NSDictionary *)hwInfo;

//#ifdef __INTERNAL_TESTING_API__
/*
 从设备获取 passcode 成功
 @param result 0=成功 否则失败
 */
//- (void)XPGWifiDevice:(XPGWifiDevice *)device didGetPasscode:(int)result;

/*
 获取模块日志
 @param wifilog wifi模块日志
 @see 触发函数 设备绑定或登录
 */
//- (void)XPGWifiDevice:(XPGWifiDevice *)device didShowWifiLog:(NSString *)wifilog;

/*
 显示接收到的二进制数据
 @param data 接收到的二进制数据
 @see 触发函数：设备操作或设备上报
 */
//- (void)XPGWifiDevice:(XPGWifiDevice *)device didShowRevieveData:(NSString *)data;
#define DATA_CMD                        @"cmd"
- (void)connectAndupdateAllDevice {
    for (Device *device in _items) {
//        if (device.xpgDevice.isOnline)
            [device.xpgDevice login:myAppDelegate.uid token:myAppDelegate.token];
//        [device.xpgDevice write:@{DATA_CMD: @(2)}];//读所有数据
    }
}

//因为有些地方是重置了xpgDevice的delegate，所以需要加这个；后面需要替换
- (void)setAllxpgDeviceDelegateIsMyself;{
    for (Device *device in _items) {
        device.xpgDevice.delegate = self;
    }
}

- (void)setAllDeviceDelegate:(id<XPGWifiDeviceDelegate>) delegate;{
    for (Device *device in _items) {
        device.deleagete = delegate;
    }
}

@end
